#include "program.h"
#include "getpidpackage.h"

#define SAVE_PID_COUNT_MAX 20

Program::Program()
{

}
Program::~Program()
{
}

Program &Program::get_instance()
{
    static Program instance;
    return instance;
}

void Program::CombinationPAT_Info(PROGRAM_INFO *pstProgramInfo, int iProgramCount, PAT_INFO *pstPAT_Info)
{
    int iLoopTime = 0;

    for (iLoopTime = 0; iLoopTime < iProgramCount; iLoopTime++)
    {
        pstProgramInfo[iLoopTime].uiProgramNumber = pstPAT_Info[iLoopTime].uiProgramNumber;
        pstProgramInfo[iLoopTime].uiPMT_PID = pstPAT_Info[iLoopTime].uiPMT_PID;
    }
}

void Program::CombinationPMT_Info(PROGRAM_INFO *pstProgramInfo, int iProgramCount, PMT_INFO *pstPMT_Info)
{
    int iLoopTime = 0;
    int iStreamIndex = 0;

    for (iLoopTime = 0; iLoopTime < iProgramCount; iLoopTime++)
    {
        for (iStreamIndex = 0; iStreamIndex < iProgramCount; iStreamIndex++)
        {
            if (pstProgramInfo[iLoopTime].uiProgramNumber == pstPMT_Info[iStreamIndex].uiProgramNumber)
            {
                pstProgramInfo[iLoopTime].uiVideoPID = pstPMT_Info[iStreamIndex].uiVideoPID;
                memcpy(pstProgramInfo[iLoopTime].auiAudioPID, pstPMT_Info[iStreamIndex].auiAudioPID, AUDIION_MAX * sizeof(unsigned int));
            }
        }
    }
}

void Program::CombinationSDT_Info(PROGRAM_INFO *pstProgramInfo, int iProgramCount, SDT_INFO *pstSDT_Info)
{
    int iLoopTime = 0;
    int iServiceIndex = 0;

    for (iLoopTime = 0; iLoopTime < iProgramCount; iLoopTime++)
    {
        for (iServiceIndex = 0; iServiceIndex < iProgramCount; iServiceIndex++)
        {
            if (pstProgramInfo[iLoopTime].uiProgramNumber == pstSDT_Info[iServiceIndex].uiServiceId)
            {
                pstProgramInfo[iLoopTime].uiFreeCA_Mode = pstSDT_Info[iServiceIndex].uiFreeCA_Mode;
                pstProgramInfo[iLoopTime].uiEIT_PresentFollowingFlag = pstSDT_Info[iServiceIndex].uiEIT_PresentFollowingFlag;
                pstProgramInfo[iLoopTime].uiEIT_ScheduleFlag = pstSDT_Info[iServiceIndex].uiEIT_ScheduleFlag;
                memcpy(pstProgramInfo[iLoopTime].aucProgramNanme, pstSDT_Info[iServiceIndex].aucProgramNanme,
                        NAME_LENGTH_MAX * sizeof(unsigned char));
            }
        }
    }
}

void Program::CombinationAllInfo(PROGRAM_INFO *pstProgramInfo, int iProgramCount, PAT_INFO *pstPAT_Info, PMT_INFO *pstPMT_Info,
        SDT_INFO *pstSDT_Info)
{
    CombinationPAT_Info(pstProgramInfo, iProgramCount, pstPAT_Info);
    CombinationPMT_Info(pstProgramInfo, iProgramCount, pstPMT_Info);
    CombinationSDT_Info(pstProgramInfo, iProgramCount, pstSDT_Info);
}

void Program::PrintAllProgramInfo(PROGRAM_INFO *pstProgramInfo, int iProgramCount)
{
    int iProgramIndex = 0;

    printf("out put all the program information \n");
    printf("ProgramId PMT_PID   FreeCA  ProgramName           VideoPID  AudioPID1 AudioPID2\n");
    for (iProgramIndex = 0; iProgramIndex < iProgramCount; iProgramIndex++)
    {
        printf("%5d  ", pstProgramInfo[iProgramIndex].uiProgramNumber);
        printf("   %5d", pstProgramInfo[iProgramIndex].uiPMT_PID);
        if (0 == pstProgramInfo[iProgramIndex].uiFreeCA_Mode)
        {
            printf("     yes");
        }
        else
        {
            printf("      no");
        }
        printf("    %-25s", pstProgramInfo[iProgramIndex].aucProgramNanme);
        printf("%5d", pstProgramInfo[iProgramIndex].uiVideoPID);
        printf("    %5d", pstProgramInfo[iProgramIndex].auiAudioPID[0]);
        printf("    %5d\n", pstProgramInfo[iProgramIndex].auiAudioPID[1]);
    }
}

void Program::GetAllSavePID(PROGRAM_INFO *pstProgramInfo, unsigned int *puiSavePid)
{
   int iPidCount = 0;
   int iAudioIndex = 0;
   /*----------------------------------------------------------*/
   /* get the video PID */
   /*----------------------------------------------------------*/
   if (0 != pstProgramInfo->uiVideoPID)
   {
       puiSavePid[++iPidCount] = pstProgramInfo->uiVideoPID;
   }

   /*----------------------------------------------------------*/
   /* get the audio PID */
   /*----------------------------------------------------------*/
   for (iAudioIndex = 0; iAudioIndex < AUDIION_MAX; iAudioIndex++)
   {
       if (0 != pstProgramInfo->auiAudioPID[iAudioIndex])
       {
           puiSavePid[++iPidCount] = pstProgramInfo->auiAudioPID[iAudioIndex];
       }
   }
   puiSavePid[0] = iPidCount;
}

PROGRAM_INFO Program::GetProgram(PROGRAM_INFO *pstProgramInfo, int iProgramCount, unsigned int uiServiceId)
{
    int iProgramIndex = 0;
    PROGRAM_INFO stProgramInfoTemp = {0};

    for (iProgramIndex = 0; iProgramIndex < iProgramCount; iProgramIndex++)
    {
        if (pstProgramInfo[iProgramIndex].uiProgramNumber == uiServiceId)
        {
            return pstProgramInfo[iProgramIndex];
        }
    }
    return stProgramInfoTemp;
}

void Program::NormalFileName(unsigned char *pucFileName)
{
    unsigned char *pucTemp = pucFileName;

    /*----------------------------------------------------------*/
    /* the file name can't exist / \ : * ? " < > | */
    /*----------------------------------------------------------*/
    while ((*pucTemp) != '\0')
    {
        if (('/' == (*pucTemp)) || ('\\' == (*pucTemp)) || (':' == (*pucTemp)) || ('*' == (*pucTemp)) || ('?' == (*pucTemp))
                || ('"' == (*pucTemp)) || ('<' == (*pucTemp)) || ('>' == (*pucTemp)) || ('|' == (*pucTemp)))
        {
            (*pucTemp) = ' ';
        }
        pucTemp++;
    }
}

int Program::SaveVideoAndAudio(PROGRAM_INFO *pstProgramInfo, int iProgramCount, FILE *pfTsFile, int iTsPosition, int iTsLength,
        unsigned int uiInServiceId)
{
    int iReturn = 0;
    FILE *pfSaveFile = NULL;
    unsigned int auiSavePid[SAVE_PID_COUNT_MAX] = {0};
    unsigned char aucSaveFileName[NAME_LENGTH_MAX] = {0};
    PROGRAM_INFO stSaveProgramInfo = {0};

    stSaveProgramInfo = GetProgram(pstProgramInfo, iProgramCount, uiInServiceId);
    if (stSaveProgramInfo.uiProgramNumber == uiInServiceId)
    {
        GetAllSavePID(&stSaveProgramInfo, auiSavePid);
        if (0 != auiSavePid[0]) //exist video or audio(auiSavePid[0] represent the count of PID)
        {
            sprintf((char*)aucSaveFileName, "%s.ts", stSaveProgramInfo.aucProgramNanme);
            NormalFileName(aucSaveFileName);
            pfSaveFile = fopen((char *)aucSaveFileName, "wb");

            if (NULL == pfSaveFile)
            {
                printf("open the save file error\n");
                return -1;
            }
            if (-1 == GetPidPackage::get_instance().SavePID_Packege(pfTsFile, iTsPosition, iTsLength, auiSavePid, pfSaveFile))
            {
                iReturn = -1;
            }
            fclose(pfSaveFile);
            printf("\n save success and the save file name is    %s\n\n", aucSaveFileName);
        }
        else
        {
            printf("\n the %d program not exist video or audio input again \n\n", stSaveProgramInfo.uiProgramNumber);
        }
    }
    else
    {
        printf("no the program \n");
    }
    return iReturn;
}

void Program::PrintEIT_ExistState(PROGRAM_INFO *pstProgramInfo, int iProgramCount)
{
    int iProgramIndex = 0;

    printf("the state of the EIT table (1:exist 0:not exist)\n ");
    printf("Service_id EIT(0x4e) EIT(0x50)\n");
    for (iProgramIndex = 0; iProgramIndex < iProgramCount; iProgramIndex++)
    {
        printf("%5d", pstProgramInfo[iProgramIndex].uiProgramNumber);
        printf("         %d", pstProgramInfo[iProgramIndex].uiEIT_PresentFollowingFlag);
        printf("         %d\n", pstProgramInfo[iProgramIndex].uiEIT_ScheduleFlag);
    }
}
